package com.yishoubao.demo.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yishoubao.demo.utils.HttpUtils;
import com.yishoubao.demo.utils.MerchantConfig;
import com.yishoubao.demo.utils.SignUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author YASSER
 * @version: 1.0.0
 * @description: <文件描述>
 * @modified: <文件修改说明>
 */
@Controller
@RequestMapping("/pay")
public class PayController {

    private final static Logger logger = LoggerFactory.getLogger(PayController.class);

    /**
     * 模拟客户端下单接口
     * @param amount -- 支付金额，单位元，2位小数
     * @param payChannelType -- 充值渠道：0支付宝，1微信，2QQ
     * @return
     */
    @ResponseBody
    @RequestMapping("/makeOrder")
    public Object makeOrder(Double amount, String payChannelType, String merSubCode) {
        // 创建订单号，需要商户内唯一，6-18位纯数字
        String orderNo = String.valueOf(System.currentTimeMillis());
        Map<String, String> requestMap = new HashMap<>(6);
        // 商户号
        requestMap.put("merCode", MerchantConfig.MER_CODE);
        requestMap.put("makeOrderType", "0");
        // 默认值，充值渠道：0支付宝，1微信，2QQ
        requestMap.put("payChannelType", payChannelType);
        // 下游商户号
        requestMap.put("merSubCode", merSubCode);
        // 订单金额，单位元，2位小数
        requestMap.put("orderAmount", formatAmount(amount));
        // 支付结果回调通知地址
        requestMap.put("notifyUrl", MerchantConfig.PAY_ORDER_NOTIFY_URL);
        // 订单号，需要商户内唯一，长度6-18位纯数字
        requestMap.put("orderNo", orderNo);
        // 生成签名
        String sign = SignUtils.getSignOfMD5(requestMap, MerchantConfig.MER_KEY);
        requestMap.put("sign", sign);
        logger.info("requestMap:{}", requestMap);
        // 发起获取支付数据请求
        String responseStr = HttpUtils.doPost(MerchantConfig.PAY_ORDER_GATEWAY, requestMap);
        // 解析获取到的json字符串
        /**
         * 返回的数据为:
         {
             "msg": "订单创建成功，订单有效时间120分钟，超时支付请联系管理员",
             "merCode": "8001",
             "payChannelType": "0",
             "realAmount": "1.00",
             "code": "1000",
             "orderNo": "1541562482294",
             "orderAmount": "1.00",
             "qrCodeUrl": "http://ysb.fxinpay.com/gateway/pay/skip?merCode=8001&orderNo=1541562482294&sign=d8ca98911d7e7d59d3edc35aa586ea1e",
             "sign": "14da39b27dfa629b487f49b599371ed6",
             "status": true,
             "makeOrderType": "1"
         }
         */
        JSONObject jsonObject = null;
        if (responseStr != null && !Objects.equals(responseStr, "")) {
            try {
                jsonObject = JSON.parseObject(responseStr);
                if(jsonObject.getBoolean("status") && Objects.equals("1000", jsonObject.get("code"))) {
                    // 如果status为true 和  code为1000。则表示下单成功
                    // 处理下单成功的业务逻辑

                    // ......

                }else {
                    // 表示下单失败

                }
            } catch (Exception e){
                jsonObject.put("msg", "网络连接错误");
            }
        }
        return jsonObject;
    }

    /**
     * 处理支付结果的回调通知
     * @param request
     * @param response
     */
    @RequestMapping("/notify")
    public void handleNotify(String status,
                               String msg,
                               String code,
                               String merCode,
                               String payChannelType,
                               String orderNo,
                               String orderAmount,
                               String realPayAmount,
                               String sign,
                               HttpServletRequest request, HttpServletResponse response) throws IOException {
        Map<String, String> notifyMap = new HashMap<>(5);
        notifyMap.put("merCode", merCode);
        notifyMap.put("payChannelType", payChannelType);
        notifyMap.put("orderNo", orderNo);
        notifyMap.put("orderAmount", orderAmount);
        notifyMap.put("realPayAmount", realPayAmount);
        logger.info("回调通知数据:{}", notifyMap);
        // 处理结果返回字符串
        String handleResultStr = "签名错误";
        // 计算签名
        String md5Sign = SignUtils.getSignOfMD5(notifyMap, MerchantConfig.MER_KEY);
        if(Objects.equals(md5Sign, sign)) {
            if (Objects.equals(status, String.valueOf(Boolean.TRUE)) && Objects.equals("1015", code)){
                // 如果status为true, code = 1015 表示付款成功

                // 处理付款成功业务逻辑。此处需要防止重复通知

                // ......

                // 处理成功
                handleResultStr =  "SUCCESS";
            }
        }
        // 将处理结果返回给收款吧系统，如果返回SUCCESS，则表示处理成功，则收款吧系统不再发起通知。否则收款吧会定时3分钟再次发起，总共发起3次
        PrintWriter printWriter = response.getWriter();
        printWriter.write(handleResultStr);
        printWriter.flush();
    }

    /**
     * 将订单金额格式化为2位小数的字符串
     * @param amount -- 订单金额，单位元，2位小数
     * @return
     */
    private String formatAmount(double amount) {
        BigDecimal bigDecimal = new BigDecimal(String.valueOf(amount));
        return bigDecimal.setScale(2, BigDecimal.ROUND_DOWN).toString();
    }

    /**
     * 查询订单状态
     * @param orderNo -- 订单号
     * @return
     */
    @ResponseBody
    // @RequestMapping("/queryOrderStatus")
    public Object queryOrderStatus(String orderNo) {
        if(StringUtils.isBlank(orderNo)) {
            return null;
        }
        Map<String, String> requestMap = new HashMap<>(3);
        // 商户号
        requestMap.put("merCode", MerchantConfig.MER_CODE);
        // 订单号，需要商户内唯一，长度6-18位纯数字
        requestMap.put("orderNo", orderNo);
        // 生成签名
        String sign = SignUtils.getSignOfMD5(requestMap, MerchantConfig.MER_KEY);
        requestMap.put("sign", sign);
        logger.info("requestMap:{}", requestMap);
        // 发起获取支付数据请求
        String responseStr = HttpUtils.doGet(MerchantConfig.QUERY_PAY_ORDER_STATUS_GATEWAY, requestMap);
        logger.info("查询订单状态响应数据:{}", responseStr);
        JSONObject jsonObject = null;
        if (StringUtils.isNotBlank(responseStr)) {
            // 解析获取到的json字符串
            jsonObject = JSON.parseObject(responseStr);
            if(jsonObject.getBoolean("status") && Objects.equals("1000", jsonObject.get("code"))) {
                // 如果status为true 和  code为1000。则表示付款成功
                // 处理的业务逻辑

                // ......

            }else {
                // 处理的业务逻辑

                // ......

            }
        }
        return jsonObject;
    }
}
